/**
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ABCKIT_WRAPPER_MOCK_LOGGER_H
#define ABCKIT_WRAPPER_MOCK_LOGGER_H

#include <cstdint>
#include <bitset>
#include <sstream>
#include <iostream>

namespace ark {
/**
 * @brief Logger
 * mock logger impl, use libarkbase utils/logger.h
 */
class Logger {
public:
    enum Component : uint32_t {
        ALLOC,
        MM_OBJECT_EVENTS,
        ASSEMBLER,
        CLASS_LINKER,
        COMMON,
        CORE,
        GC,
        GC_TRIGGER,
        REF_PROC,
        INTERPRETER,
        FUZZER,
        COMPILER,
        LLVM,
        PANDAFILE,
        MEMORYPOOL,
        RUNTIME,
        TRACE,
        DPROF,
        DEBUGGER,
        TOOLING,
        INTEROP,
        VERIFIER,
        COMPILATION_QUEUE,
        DISASSEMBLER,
        ABC2PROGRAM,
        ZIPARCHIVE,
        BYTECODE_OPTIMIZER,
        AOT,
        EVENTS,
        DFX,
        SCHEDULER,
        QUICKENER,
        IRTOC,
        HOTRELOAD,
        PROFILER,
        COROUTINES,
        ATOMICS,
        ES2PANDA,
        STATIC_LINKER,
        TASK_MANAGER,
        STDLIB,
        SDK,
        ARK_GUARD,
        ABCKIT_WRAPPER,
        ANI,
        ETS,
        ETS_NAPI,
        ETS_INTEROP_JS,
        LAST
    };

    using ComponentMask = std::bitset<Component::LAST>;
    using Formatter = void (*)(FILE *stream, int level, const char *component, const char *message);

    /**
     * @brief Logger Level
     */
    enum class Level {
        FATAL = 0,
        ERROR = 1,
        WARNING = 2,
        INFO = 3,
        DEBUG = 4,
        LAST,
    };

    /**
     * Logger Constructor
     * @param logLevel logLevel
     * @param logLevelStr logLevel str DEBUG, INFO, ...
     * @param component component for sub systems
     */
    Logger(const Level logLevel, const std::string &logLevelStr, const std::string &component)
        : logLevel_(logLevel),
          logLevelStr_(logLevelStr),
          component_(component)
    {
    }

    /**
     * Destructor
     * print log by std stream cerr or cout
     */
    ~Logger()
    {
        if (stream_.str().empty()) {
            return;
        }

        if (logLevel_ <= Level::WARNING) {
            std::cerr << "[ Ark" << component_ << " ][" << logLevelStr_ << "]" << stream_.str() << std::endl;
        } else {
            std::cout << "[ Ark" << component_ << " ][" << logLevelStr_ << "]" << stream_.str() << std::endl;
        }
    }

    /**
     * @brief get logger stream
     * @return log stream
     */
    std::ostream &GetStream()
    {
        return stream_;
    }

    static void InitializeStdLogging(Level level, ComponentMask componentMask, Formatter formatter = nullptr)
    {
        (void)level;
        (void)componentMask;
        (void)formatter;
    }

    static void InitializeFileLogging(const std::string &logFile, Level level, ComponentMask componentMask,
                                      bool isFastLogging = false, Formatter formatter = nullptr)
    {
        (void)logFile;
        (void)level;
        (void)componentMask;
        (void)isFastLogging;
        (void)formatter;
    }

private:
    Level logLevel_ = Level::INFO;
    std::string logLevelStr_;
    std::string component_;
    std::ostringstream stream_;
};
} // namespace ark

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define IMPL_LOG(level, component) ark::Logger(ark::Logger::Level::level, #level, #component).GetStream()

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_DEBUG(component) IMPL_LOG(DEBUG, component)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_INFO(component) IMPL_LOG(INFO, component)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_WARNING(component) IMPL_LOG(WARNING, component)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_ERROR(component) IMPL_LOG(ERROR, component)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG_FATAL(component) IMPL_LOG(FATAL, component)

// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define LOG(level, component) LOG_##level(component)

#endif  // ABCKIT_WRAPPER_MOCK_LOGGER_H